/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.gestionabsences.form;

import com.gestionabsences.beans.MapStudents;
import com.gestionabsences.beans.ResultRequest;
import com.gestionabsences.config.DAOFactory;
import com.gestionabsences.database.ToolsRequest;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;

/**
 *
 * @author Krystle
 */
public class FormSecretary {
    public static final String CHAMP_NBRE_ABSENCES = "nbrAbsences";
    public static final String CHAMP_OPERATOR = "operator";
    public static final String CHAMP_ETUDIANT = "etudiant";
    public static final String CHAMP_RANGE_QUERY = "rangeQuery";
    public static final String CHAMP_ERREUR = "erreur";
    
    private Map<String, String> erreurs;
    private DAOFactory dao;
    private MapStudents mapStudents;
    
    private String formerValNbreAbsences;
    private String formerValOperator;
    private String formerValRange;
    private String formerValINE;
    
    public FormSecretary(DAOFactory dao, MapStudents listeEtudiants) {
	this.erreurs = new HashMap<String, String>();
	this.mapStudents = listeEtudiants;
	this.dao = dao;
    }
    
    public ResultRequest creationResultat(HttpServletRequest request) {

	String nbrAbsences = getValeurChamp(request, CHAMP_NBRE_ABSENCES);
	String operator = getValeurChamp(request, CHAMP_OPERATOR);
	String ineEtudiant = getValeurChamp(request, CHAMP_ETUDIANT);
	String range = getValeurChamp(request, CHAMP_RANGE_QUERY);

	double nbr_absences = -1;
	
	try {
	    validationRange(range);

	    if (range.compareTo("PARTICULAR_STUDENT") != 0) {
		try {
		    validationOperator(operator);

		    if(operator.compareTo(">=") == 0 && range.compareTo("IN_ONE") != 0) {
			throw new Exception("L'opérateur >= n'est compatible que avec \" Dans un des cours\"");
		    }
		    
		    if(operator.compareTo(">") == 0 && range.compareTo("SOME") != 0) {
			throw new Exception("L'opérateur > n'est compatible que avec \" Dans des cours\"");
		    }
		    
		    if(operator.compareTo("ALWAYS") != 0 && operator.compareTo("NEVER") != 0)
		    {
			try {
			    nbr_absences = validationNbreAbsences(nbrAbsences, operator);
			} catch (Exception e) {
			    setErreur(CHAMP_NBRE_ABSENCES, e.getMessage());
			}
		    }
		} catch (Exception e) {
		    setErreur(CHAMP_OPERATOR, e.getMessage());
		}
	    } else {
		try {
		    validationEtudiant(ineEtudiant, range);
		} catch (Exception e) {
		    setErreur(CHAMP_ETUDIANT, e.getMessage());
		}
	    }
	} catch (Exception e) {
	    setErreur(CHAMP_RANGE_QUERY, e.getMessage());
	}
	
	ResultRequest res = null;
	
	if( erreurs.isEmpty() ) {
	    formerValINE = ineEtudiant;
	    formerValRange = range;
	    formerValNbreAbsences = nbrAbsences;
	    formerValOperator = operator;
	    
	    res = createResultFromArgs(range, operator, nbr_absences, ineEtudiant);
	    if(res != null) {
		if( !res.isResultatPresent() ) {
		res = null;
		}
	    }
	} else {
	    System.out.println( erreurs.toString() );
	}
	
	return res;
    }
    
    private ResultRequest createResultFromArgs(String range, String operator, double nbrAbsences, String ineEtudiant) {
	ResultRequest res = null;
	
	ArrayList<String> tabColonnes = new ArrayList<String>();
	
	String sql_req = "SELECT * FROM ";
	
	if (range.compareTo("PARTICULAR_STUDENT") == 0) {
	    sql_req += "getAbsencesFor('" + ineEtudiant + "');";
	    
	    tabColonnes.add("matiere");
	    tabColonnes.add("heure");
	    tabColonnes.add("nom_enseignant");
	    tabColonnes.add("prenom_enseignant");
	    tabColonnes.add("justification");
	    tabColonnes.add("credibilite");
	    
	} else {
	    tabColonnes.add("ine");
	    tabColonnes.add("nom");
	    tabColonnes.add("prenom");

	    if (range.compareTo("ALL") == 0) {
		if (operator.compareTo("ALWAYS") == 0) {
		    sql_req += "getAlwaysAbsentForEverything();";
		} else {
		    sql_req += "getNeverAbsent();";
		}
	    } else if (range.compareTo("SOME") == 0) {
		sql_req += "getMoreThanXNotJustified(" + (int) nbrAbsences + ");";
	    } else { // IN_ONE
		sql_req += "getAtLeastXNotJustifiedInOneCourse(" + (int) nbrAbsences + ")";
	    }
	}
	
	System.out.println(sql_req);
	
	Connection connexion = null;
	
	try {
	    connexion = dao.getConnection();
	    
	    PreparedStatement preparedStatement = null;
	    ResultSet resultSet = null;
	
	    try {
		preparedStatement = ToolsRequest.prepareRequest( connexion, sql_req, false);
		//setErreur( CHAMP_ERREUR, preparedStatement.toString() );
		System.out.println("query :  " + preparedStatement.toString());
		
		resultSet = preparedStatement.executeQuery();
		
		res = new ResultRequest(resultSet, tabColonnes.toArray());
				
	    } catch(Exception e) {
		setErreur( CHAMP_ERREUR, preparedStatement.toString() + " => " + e.getMessage() );
	    }
	    finally {
		ToolsRequest.close(preparedStatement, resultSet);
	    }
	} catch (SQLException e) {
	    setErreur( CHAMP_ERREUR, e.getMessage() );
	}
	finally {
	    ToolsRequest.close(connexion);
	}
	
	return res;
    }
    
    private void validationRange(String range) throws Exception {
	final String OPTION1 = "ALL";
	final String OPTION2 = "SOME";
	final String OPTION3 = "IN_ONE";
	final String OPTION4 = "PARTICULAR_STUDENT";
	
	if( range.compareTo(OPTION1) != 0 && range.compareTo(OPTION2) != 0 && range.compareTo(OPTION3) != 0 && range.compareTo(OPTION4) != 0 ) {
	    throw new Exception( "La portée '" + range + "' n'est pas valable." );
	}
    }
    
    private void validationEtudiant( String etudiant, String range ) throws Exception {
	if(range.compareTo("PARTICULAR_STUDENT") == 0) {
	    if (etudiant != null) {
		if (!this.mapStudents.containsKey(etudiant)) {
		    throw new Exception("L'étudiant spécifié n'existe pas.");
		}
	    } else {
		throw new Exception("Un étudiant doit être spécifié pour faire la recherche.");
	    }
	}
    }
    
    private void validationOperator(String operator) throws Exception {
	final String OPTION1 = ">=";
	final String OPTION2 = ">";
	final String OPTION3 = "NEVER";
	final String OPTION4 = "ALWAYS";
	
	if( operator.compareTo(OPTION1) != 0 && operator.compareTo(OPTION2) != 0 && operator.compareTo(OPTION3) != 0 && operator.compareTo(OPTION4) != 0 ) {
	    throw new Exception( "L'opérateur '" + operator + "' n'est pas valable." );
	}
    }
    
    
    private double validationNbreAbsences(String nbrAbsences, String operator) throws Exception {
	double temp;
	
	if(operator.compareTo("NEVER") == 0 || operator.compareTo("ALWAYS") == 0 ) {
	    return -2;
	}
	
	if (nbrAbsences != null) {
	    try {
		temp = Double.parseDouble(nbrAbsences);
		if (temp < 0) {
		    throw new Exception("Le nombre d'absence doit être un nombre positif.");
		}
	    } catch (NumberFormatException e) {
		temp = -1;
		throw new Exception("Le nombre d'absence doit être un nombre.");
	    }
	} else {
	    temp = -1;
	    throw new Exception("Merci d'entrer un nombre d'absence.");
	}
	
	return temp;
    }
    
    public String getFormerValINE() {
	return this.formerValINE;
    }
    
    public String getFormerValRange() {
	return this.formerValRange;
    }
    
    public String getFormerValOperator() {
	return this.formerValOperator;
    }
    
    public String getFormerValNbreAbsences() {
	return this.formerValNbreAbsences;
    }
        
    public Map<String, String> getErreurs() {
        return erreurs;
    }
    
    private void setErreur( String champ, String message ) {
	String previous = erreurs.get(champ);
	if(previous != null) {
	    erreurs.put( champ, previous + message );
	}
	else {
	    erreurs.put( champ, message );
	}
	
    }
    
    private static String getValeurChamp( HttpServletRequest request, String nomChamp ) {
        String valeur = request.getParameter( nomChamp );
        if ( valeur == null || valeur.trim().length() == 0 ) {
            return null;
        } else {
            return valeur;
        }
    }
}
